#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <omp.h>
#include <sys/timeb.h>
#include "preprocessor.h"

// Funcao que pega o tempo 
long getmillis() {
    struct timeb mtimebuffer;

    ftime(&mtimebuffer);
    return 1000 * mtimebuffer.time + mtimebuffer.millitm;
}

int main(int argc, char * args[]) {


    //     Variaveis auxiliares utilizada por todo o programa
    int i;
    int j;

    //     Variavel que contem o numero total de palavras
    int counter_wordTotal = 0;
    //     Variavel que contem o numero encontrado de palavras
    int counter_wordParcial = 0;
    //     Variavel que contem o tamanho de uma determinada palavra
    int words_size[46] = {0};


    FILE *pFile;

    /* Arvores primarias */
    /* Arvore primaria que contem as palavras completas */
    node *words = NULL;
    node *words5 = NULL;
    node *words10 = NULL;
    node *words15 = NULL;
    node *words20 = NULL;
    node *words25 = NULL;

    /* Arvores secundarias */
    /* Arvore secundaria que contem as palavras encontradas completas */
    node *words2_5 = NULL;
    node *words2_10 = NULL;
    node *words2_15 = NULL;
    node *words2_20 = NULL;
    node *words2_25 = NULL;


    //     Variaveis para calcular o tempo
    long mtimea;
    long mtimeb;

    //     Pre-processador do texto
    words = preProcessor(&counter_wordTotal, words_size, &words5, &words10, &words15, &words20, &words25);


    pFile = fopen("res_word_3.txt", "w");
    //     Variaveis auxiliares do algoritmo de aleatoriedade
    int n;
    int w;
    char c;
    //     Variavel que recebe o ID da thread
    int th_id;
    //     Flag que verifica se teve varias palavras nao encontradas e troca de alfabeto
    int flag = 0;
    //     Contadores gerais de porcentagem e tempo do programa
    double porcent = 0.0;
    int porcent_int = 0;
    int words_left = 0;
    mtimeb = getmillis();


    //      Nós auxiliares
    node* aux;
    node* aux_tree;
    //         Alfabeto utilizado
    char chars[27] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
        'x', 'y', 'z', '{'};
    int r;
    th_id = omp_get_thread_num();

    srand(time(NULL) * th_id);
    // Inicio da geração aleatoria de palavras
    while (1) {
        char s[50] = {0};

        if (flag > 10000) {
            srand(time(NULL) * th_id);
            flag = 0;
            r = rand() % 27;

            for (w = 0; w < 27; w++)
                chars[w] = ((chars[w] - 'a') + r) % 27 + 'a';

        }
        /* loop que limita o tamanho da palavra a ser criada */
        for (i = 1; i <= 100; i++) {
            flag++;
            /* gera a palavra de tamanho i */
            for (j = 1; j <= i; j++) {
                /* gera-se a palavra aleatoria */
                n = rand() % 27;
                c = chars[n];
                s[j - 1] = c;
                // Verifica-se a palavra foi bem formada
                if (findN(s, words, j) == NULL)
                    j = i;

                /*
                 * Todos os blocos de if abaixo seguem a mesma ideia
                 * portanto comentaremos o funcionamento do primeiro, que eh
                 * equivalente para todos os outros nessa funcao
                 */
                /* se encontrou a palavra na arvore de 0 a 5 letras  */
                aux = find(s, words5);
                if (aux != NULL) {
                    /* procura-se pela mesma na arvore secundaria de 0 a 5 letras */
                    if (find(s, words2_5) == NULL) {

                        /* reset a variavel de rotacao do alfabeto */
                        flag = 0;
                        /* insere-se a palavra na arvore secundaria */
                        words2_5 = insert(s, words2_5);

                        while (aux->rowSub != NULL) {
                            aux_tree = findSub(getRowNode(aux), words, 0);
                            if (aux_tree->complete) {
                                fprintf(pFile, "%s\n", aux_tree->word);
                                /* incrementa a quantidade de palavras encontradas */
                                counter_wordParcial++;
                            }

                        }
                        // Calculo de tempo e palavras encontradas
                        if (words_left != counter_wordTotal - counter_wordParcial) {
                            if (porcent_int % 10 == 0 || porcent >= 99.0) {
                                mtimea = getmillis();
                                words_left = counter_wordTotal - counter_wordParcial;
                                printf("Tempo de %f eh = %d, faltam %d palavras\n", porcent, mtimea - mtimeb, words_left);
                            }

                            porcent = (counter_wordParcial * 100.0) / counter_wordTotal;
                            porcent_int = (int) porcent;
                        }

                    }
                }

                /* o mesmo que o anterior para a arvore de 5 a 10 letras */
                aux = find(s, words10);
                if (aux != NULL) {
                    if (find(s, words2_10) == NULL) {

                        flag = 0;
                        words2_10 = insert(s, words2_10);
                        while (aux->rowSub) {
                            aux_tree = findSub(getRowNode(aux), words, 1);
                            if (aux_tree->complete) {
                                fprintf(pFile, "%s\n", aux_tree->word);

                                counter_wordParcial++;
                            }

                        }
                        if (words_left != counter_wordTotal - counter_wordParcial) {
                            if (porcent_int % 10 == 0 || porcent >= 99.0) {
                                mtimea = getmillis();
                                words_left = counter_wordTotal - counter_wordParcial;
                                printf("Tempo de %f eh = %d, faltam %d palavras\n", porcent, mtimea - mtimeb, words_left);
                            }

                            porcent = (counter_wordParcial * 100.0) / counter_wordTotal;
                            porcent_int = (int) porcent;
                        }

                    }
                }

                /* o mesmo que o anterior para a arvore de 10 a 15 letras */
                aux = find(s, words15);
                if (aux != NULL) {
                    if (find(s, words2_15) == NULL) {

                        flag = 0;
                        words2_15 = insert(s, words2_15);
                        while (aux->rowSub) {
                            aux_tree = findSub(getRowNode(aux), words, 2);
                            if (aux_tree->complete) {
                                fprintf(pFile, "%s\n", aux_tree->word);
                                counter_wordParcial++;
                            }

                        }

                        if (words_left != counter_wordTotal - counter_wordParcial) {
                            if (porcent_int % 10 == 0 || porcent >= 99.0) {
                                mtimea = getmillis();
                                words_left = counter_wordTotal - counter_wordParcial;
                                printf("Tempo de %f eh = %d, faltam %d palavras\n", porcent, mtimea - mtimeb, words_left);
                            }

                            porcent = (counter_wordParcial * 100.0) / counter_wordTotal;
                            porcent_int = (int) porcent;
                        }

                    }
                }
                /* o mesmo que o anterior para a arvore de 15 a 20 letras */
                aux = find(s, words20);
                if (aux != NULL) {
                    if (find(s, words2_20) == NULL) {

                        flag = 0;
                        words2_20 = insert(s, words2_20);

                        while (aux->rowSub) {
                            aux_tree = findSub(getRowNode(aux), words, 3);

                            if (aux_tree->complete) {
                                fprintf(pFile, "%s\n", aux_tree->word);
                                counter_wordParcial++;
                            }

                        }

                        if (words_left != counter_wordTotal - counter_wordParcial) {
                            if (porcent_int % 10 == 0 || porcent >= 99.0) {
                                mtimea = getmillis();
                                words_left = counter_wordTotal - counter_wordParcial;
                                printf("Tempo de %f eh = %d, faltam %d palavras\n", porcent, mtimea - mtimeb, words_left);
                            }

                            porcent = (counter_wordParcial * 100.0) / counter_wordTotal;
                            porcent_int = (int) porcent;

                        }
                    }
                }

                /* o mesmo que o anterior para a arvore de 20 ou mais letras */
                aux = find(s, words25);
                if (aux != NULL) {
                    if (find(s, words2_25) == NULL) {

                        flag = 0;
                        words2_25 = insert(s, words2_25);

                        while (aux->rowSub) {
                            aux_tree = findSub(getRowNode(aux), words, aux->blocks);

                            if (aux_tree->complete) {
                                fprintf(pFile, "%s\n", aux_tree->word);
                                counter_wordParcial++;
                            }

                        }

                        if (words_left != counter_wordTotal - counter_wordParcial) {
                            if (porcent_int % 10 == 0 || porcent >= 99.0) {
                                mtimea = getmillis();
                                words_left = counter_wordTotal - counter_wordParcial;
                                printf("Tempo de %f eh = %d, faltam %d palavras\n", porcent, mtimea - mtimeb, words_left);
                            }

                            porcent = (counter_wordParcial * 100.0) / counter_wordTotal;
                            porcent_int = (int) porcent;

                        }
                    }
                }
                // Se o numero de palavras encontradas for o mesmo que o total então termina o programa
                if (counter_wordParcial == (counter_wordTotal))
                    exit(0);
            }
        }
    }



    fclose(pFile);








    return 0;
}


